package m.jclecai.com.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;

import java.util.List;

import m.jclecai.com.R;
import m.jclecai.com.bean.BitWheelInfo;
import m.jclecai.com.utils.BitmapUtil;


/**
 */

public class BitView extends View {

    boolean allowClick = true;
    private Object obj = new Object();

    /**
     * 控件要绘制的宽度
     **/
    private int mDrawWidth;

    /**
     * 避免重复计算宽度
     **/
    private boolean hasMeasured = false;

    /**
     * 500毫秒内的点击被认为是点击事件
     **/
    private long timeClick = 500;

    /**
     * 保存点击的时间
     **/
    private long nowClick;

    /**
     * 被选中的position,默认第0个选中
     **/
    private int checkPosition = 0;

    /**
     * 绘画区域的图片。这边会将各个小图片拼接成一张图片
     **/
    private Bitmap fontBitmap;

    private List<BitWheelInfo> bitInfos;

    /**
     * 选项的个数
     **/
    private int mItemCount;

    /**
     * 保存的画布
     **/
    private Canvas mCanvas;

    /**
     * 非选中和选择的颜色色块
     */
    private int[] mColors = new int[]{0x00ffeb8c, 0x00ffeb8c};

    /**
     * 触摸点的坐标位置
     **/
    private float touchX;
    private float touchY;

    /**
     * 绘制盘块的范围
     */
    private RectF mRange = new RectF();

    /**
     * 绘制盘快的画笔
     */
    private Paint mArcPaint;

    /**
     * 绘制文字的画笔
     */
    private TextPaint mTextPaint;

    /**
     * 绘制分割线的画笔
     */
    private Paint mLinePaint;

    /**
     * 圆形背景的画笔
     **/
    private Paint mBackColorPaint;

    /**
     * 圆盘角度
     **/
    private volatile float mStartAngle = 0;

    /**
     * 控件的中心位置,处于中心位置。x和y是相等的
     */
    private int mCenter;

    private float screenWidth = getResources().getDisplayMetrics().widthPixels;

    /**
     * 圆形背景的宽度，这边是在1080p下的780
     **/
    private float mBackColorWidth = screenWidth - dip2px(10) * 2;

    /**
     * 内圈画盘小圆的宽度，这边是在1080p下的730，绘画区域
     **/
    private float mRangeWidth = mBackColorWidth - 50;

    /**
     * 里面的小图大小，这边是1080p下的115
     **/
    private float mLitterBitWidth = mBackColorWidth / 10;

    /**
     * 文字的大小为26px
     */
    private float mTextSize = 26;

    /**
     * 中心图片信息
     **/
    private float mCheckBitmapWidth = screenWidth / 4;//1080p下的270
    private RectF mCheckBitmapRect = new RectF();//图片绘制区域

    private Bitmap transB = null;
    private Bitmap mPanBg = BitmapFactory.decodeResource(getResources(), R.mipmap.zp_sx_bg).
            copy(Bitmap.Config.ARGB_8888, true);

    public BitView(Context context) {
        this(context, null);
    }

    public BitView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * 设置控件为正方形
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = Math.min(getMeasuredWidth(), getMeasuredHeight());
        // 中心点
        mCenter = width / 2;
        mDrawWidth = width;
        //屏幕的宽度
        setMeasuredDimension(width, width);
        init();
    }

    /**
     * 当前切图的比例都是在1080p下进行的，所以这边的比例就是1080的
     * <p>
     * mDrawWidth 表示为控件的宽度
     **/
    private float getDrawWidth(float width) {
        return width * mDrawWidth / screenWidth;
    }


    public void setBitInfos(List<BitWheelInfo> bitInfos, String type) {
        this.bitInfos = bitInfos;
        mItemCount = this.bitInfos.size();
        bitmapRecycle(mPanBg);
        if (type.equals("星座")) {
            mPanBg = BitmapFactory.decodeResource(getResources(), R.mipmap.zp_xz_bg).
                    copy(Bitmap.Config.ARGB_8888, true);
        } else {
            mPanBg = BitmapFactory.decodeResource(getResources(), R.mipmap.zp_sx_bg).
                    copy(Bitmap.Config.ARGB_8888, true);
        }
        onDrawInvalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        this.mCanvas = canvas;
        drawCanvas();
    }

    private void init() {
        if (!hasMeasured) {
            //得到各个比例下的图片大小
            mBackColorWidth = getDrawWidth(mBackColorWidth);
            mRangeWidth = getDrawWidth(mRangeWidth);
            mCheckBitmapWidth = getDrawWidth(mCheckBitmapWidth);
            mLitterBitWidth = getDrawWidth(mLitterBitWidth);
            mTextSize = TypedValue.applyDimension(
                    TypedValue.COMPLEX_UNIT_SP, mTextSize / 3, getResources().getDisplayMetrics());
            hasMeasured = true;
        }
        // 初始化绘制圆弧的画笔
        mArcPaint = new Paint();
        mArcPaint.setAntiAlias(true);
        mArcPaint.setDither(true);
        // 初始化绘制文字的画笔
        mTextPaint = new TextPaint();
        mTextPaint.setColor(0xff222222);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setDither(true);
        //圆形背景的画笔
        mBackColorPaint = new Paint();
        mBackColorPaint.setColor(0xffae6112);
        mBackColorPaint.setAntiAlias(true);
        mBackColorPaint.setDither(true);
        //未选中的分割线的画笔
        mLinePaint = new Paint();
        mLinePaint.setAntiAlias(true);
        mLinePaint.setDither(true);
        mLinePaint.setStrokeWidth(dip2px(1f));
        mLinePaint.setStyle(Paint.Style.FILL);
        mLinePaint.setColor(0xffff9406);
        // 内圈画盘
        mRange = new RectF(mCenter - mRangeWidth / 2, mCenter - mRangeWidth / 2, mCenter + mRangeWidth / 2, mCenter + mRangeWidth / 2);
        //中心图片绘制区域
        mCheckBitmapRect = new RectF(mCenter - mCheckBitmapWidth / 2, mCenter - mCheckBitmapWidth / 2, mCenter + mCheckBitmapWidth / 2, mCenter + mCheckBitmapWidth / 2);
    }

    private Bitmap getDrawItemBitmap(float tmpAngle, float sweepAngle, int position) {
        Bitmap bg = transB.copy(Bitmap.Config.ARGB_8888, true);
        Canvas itemCanvas = new Canvas(bg);
        //根据角度进行同步旋转
        itemCanvas.rotate(tmpAngle, mCenter, mCenter);
        mArcPaint.setColor(mColors[1]);
        //绘制背景颜色,从最上边开始画
        itemCanvas.drawArc(mRange, -sweepAngle / 2 - 90, sweepAngle, true, mArcPaint);
        int maingin = (int) (mCenter - mBackColorWidth / 2);
        int zj = (int) (mCenter + mBackColorWidth / 2);
        Rect dst = new Rect(maingin, maingin, zj, zj);// 屏幕位置及尺寸
        //将图片画上去
        Bitmap icon = ((BitmapDrawable) BitmapUtil.getDrawableByName(getContext(), bitInfos.get(position).text)).
                getBitmap();
        if(icon != null && !icon.isRecycled())
        itemCanvas.drawBitmap(icon, null, dst, null);
        bitmapRecycle(icon);
        return bg;
    }

    private void drawCanvas() {
        if (bitInfos == null || bitInfos.size() == 0) {
            return;
        }
        if (transB == null)
            transB = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        //绘制背景图
        mCanvas.drawBitmap(getFontBackground(), 0, 0, null);
        //画前景图片
        mCanvas.drawBitmap(getFontBitmap(), 0, 0, null);
        bitmapRecycle(fontBitmap);
        //圆形背景的画笔
        Paint trans = new Paint();
        trans.setColor(0x30ffffff);
        trans.setAntiAlias(true);
        trans.setDither(true);
        //绘制中心图片
        mCanvas.drawCircle(mCenter, mCenter, mCheckBitmapRect.height() / 2 + getDrawWidth(30), trans);
    }

    private Bitmap getFontBackground() {
        int maingin = (int) (mCenter - mBackColorWidth / 2);
        int zj = (int) (mCenter + mBackColorWidth / 2);
        Rect dst = new Rect(maingin, maingin, zj, zj);// 屏幕位置及尺寸
        fontBitmap = transB.copy(Bitmap.Config.ARGB_8888, true);
        Canvas canvas = new Canvas(fontBitmap);
        //根据角度进行同步旋转
        canvas.rotate(mStartAngle, mCenter, mCenter);
        canvas.drawBitmap(mPanBg, null, dst, null);
        return fontBitmap;
    }

    //绘制前景图片,这里包含的是图片信息和文字信息,还有背景圆弧背景展示
    private Bitmap getFontBitmap() {
        Canvas canvas = new Canvas(fontBitmap);
        //根据角度进行同步旋转
        canvas.rotate(mStartAngle, mCenter, mCenter);
        float sweepAngle = (float) (360 / mItemCount);
        float tmpAngle = checkPosition * sweepAngle;
        Bitmap drawItemBitmap = getDrawItemBitmap(tmpAngle, sweepAngle, checkPosition);
        if (drawItemBitmap != null && !drawItemBitmap.isRecycled())
            canvas.drawBitmap(drawItemBitmap, 0, 0, null);
        bitmapRecycle(drawItemBitmap);
        return fontBitmap;
    }

    /**
     * 根据当前旋转的mStartAngle计算当前滚动到的区域
     *
     * @param startAngle
     */
    public int calInExactArea(float startAngle) {
        float size = 360f / mItemCount;
        // 确保rotate是正的，且在0-360度之间
        float rotate = (startAngle % 360.0f + 360.0f) % 360.0f;

        for (int i = 0; i < mItemCount; i++) {
            // 每个的中奖范围
            if (i == 0) {
                if ((rotate > 360 - size / 2) || (rotate < size / 2)) {
                    return i;
                }
            } else {
                float from = size * (i - 1) + size / 2;
                float to = from + size;
                if ((rotate > from) && (rotate < to)) {
                    return i;
                }
            }
        }
        return -1;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!allowClick) return super.onTouchEvent(event);
        //判断按点是否在圆内
        if (!mRange.contains(event.getX(), event.getY())) {
            return true;
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchX = event.getX();
                touchY = event.getY();
                //按下时的时间
                nowClick = System.currentTimeMillis();
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                if (System.currentTimeMillis() - nowClick <= timeClick) {//此时为点击事件
                    //落点的角度加上偏移量基于初始的点的位置
                    if (mOnWheelCheckListener != null) {
                        if (!mCheckBitmapRect.contains(event.getX(), event.getY())) {
                            checkPosition = calInExactArea(getRoundArc(event.getX(), event.getY()) - mStartAngle);
                            mOnWheelCheckListener.onCheck(checkPosition);
                            onDrawInvalidate();
                        } else {
//                            mOnWheelCheckListener.start();
                        }
                    }
                }
                break;
        }
        return true;
    }

    //根据落点计算角度
    private float getRoundArc(float upX, float upY) {
        float arc = 0;
        //首先计算三边的长度
        float a = (float) Math.sqrt(Math.pow(mCenter - mCenter, 2) + Math.pow(0 - mCenter, 2));
        float b = (float) Math.sqrt(Math.pow(upX - mCenter, 2) + Math.pow(upY - mCenter, 2));
        float c = (float) Math.sqrt(Math.pow(upX - mCenter, 2) + Math.pow(upY - 0, 2));
        //判断是否为三角形
        if (a + b > c) {//两边之和大于第三边为三角形
            /**
             * 接下来计算角度
             *
             * acos((a2+b2-c2)/2ab)
             *
             * **/
            arc = (float) (Math.acos((Math.pow(a, 2) + Math.pow(b, 2) - Math.pow(c, 2)) / (2 * a * b)) * 180 / Math.PI);

            //判断是大于左边还是右边，也就是180以内还是以外
            if (upX < mCenter) {//此时是180以外的
                arc = 360 - arc;
            }
        } else {//上下边界的问题
            if (upX == mCenter) {
                if (upY < mCenter) {
                    arc = 0;
                } else {
                    arc = 180;
                }
            }
        }
        return arc;
    }

    /**
     * dp转像素
     *
     * @param dpValue
     * @return
     */
    public final int dip2px(float dpValue) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, getContext().getResources().getDisplayMetrics());
    }

    /**
     * 刷新画布
     **/
    private void onDrawInvalidate() {
        synchronized (obj) {
            invalidate();
        }
    }

    public int getCheckPosition() {
        return checkPosition;
    }


    private OnWheelCheckListener mOnWheelCheckListener;

    public void setOnWheelCheckListener(OnWheelCheckListener mOnWheelCheckListener) {
        this.mOnWheelCheckListener = mOnWheelCheckListener;
    }

    public static interface OnWheelCheckListener {
        void onCheck(int position);

        //        void start();
        void complete();
    }

    /******************************
     * 动画效果
     ******************************************/

    private static final long ONE_WHEEL_TIME = 500;
    //开始转动时候的角度，初始值为0
    private int startDegree = 0;

    //监听动画状态的监听器
    private Animation.AnimationListener al = new Animation.AnimationListener() {

        @Override
        public void onAnimationStart(Animation animation) {
            allowClick = false;
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            allowClick = true;
            if (mOnWheelCheckListener != null)
                mOnWheelCheckListener.complete();
        }
    };

    //指针转圈圈数数据源
    private int[] laps = {5, 7, 10, 15};
    //指针所指向的角度数据源，因为有6个选项，所有此处是6个值
    private int[] angles = {0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330};

    public void startAnimal(View view) {
        int lap = laps[(int) (Math.random() * 4)];
        int angle = angles[(int) (Math.random() * 6)];
        angle = 0;
        lap = 4;
        //每次转圈角度增量
        int increaseDegree = lap * 360 + angle;
        //初始化旋转动画，后面的四个参数是用来设置以自己的中心点为圆心转圈
        RotateAnimation rotateAnimation = new RotateAnimation(
                startDegree, startDegree + increaseDegree,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        //将最后的角度赋值给startDegree作为下次转圈的初始角度
        startDegree += increaseDegree;
        //计算动画播放总时间
        long time = (lap + angle / 360) * ONE_WHEEL_TIME;
        //设置动画播放时间
        rotateAnimation.setDuration(time);
        //设置动画播放完后，停留在最后一帧画面上
        rotateAnimation.setFillAfter(true);
        //设置动画的加速行为，是先加速后减速
        rotateAnimation.setInterpolator(getContext(),
                android.R.anim.accelerate_decelerate_interpolator);
        //设置动画的监听器
        rotateAnimation.setAnimationListener(al);
        //开始播放动画
        view.startAnimation(rotateAnimation);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        Log.e("bitview", "onDetachedFromWindow");
        try {
            //清空颜色
            mColors = null;
            //清空画布的绘制数据
            mRange = null;
            //回收背景图
            bitmapRecycle(mPanBg);
            //回收生肖点击效果图
            bitmapRecycle(transB);
            //将引用对象清空释放内存
            mCheckBitmapRect = null;
            mBackColorPaint.clearShadowLayer();
            mBackColorPaint.reset();
            mBackColorPaint = null;

            mLinePaint.clearShadowLayer();
            mLinePaint.reset();
            mLinePaint = null;

            mTextPaint.clearShadowLayer();
            mTextPaint.reset();
            mTextPaint = null;

            mArcPaint.clearShadowLayer();
            mArcPaint.reset();
            mArcPaint = null;

            mCanvas = null;
            //清空12生肖图
            clearBitWheel();

            bitmapRecycle(fontBitmap);

            obj = null;
            System.gc();
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("BitView", e.getLocalizedMessage());
        } catch (Error error) {
            error.printStackTrace();
            Log.e("BitView", error.getLocalizedMessage());
        }

    }

    void clearBitWheel() {
        bitInfos.clear();
        bitInfos = null;
    }

    void bitmapRecycle(Drawable d) {
        if (d != null)
            bitmapRecycle(((BitmapDrawable) d).getBitmap());
    }

    void bitmapRecycle(Bitmap b) {
        //回收背景图
        if (b != null && !b.isRecycled()) {
            b.recycle();
            b = null;
        }
    }

    void clearCanvas(Canvas canvas) {
        if (canvas == null) return;
        Paint paint = new Paint();
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawPaint(paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
    }
}
